Modern processors are designed to protect sensitive data in memory from both hardware and software attacks. Some processors provide cryptographic mechanisms for encryption, integrity, and replay protection. Memory encryption protects the confidentiality of memory-resident data. On the other hand, integrity protection prevents an attacker from causing any hidden modifications to the ciphertext (i.e., encrypted data, as opposed to plaintext which is unencrypted data) in memory, and replay protection eliminates any undetected temporal substitution of the ciphertext. In the absence of such protections, an attacker with physical access to the system can record snapshots of data lines and replay them at a later point in time.
Memory encryption is primarily designed to protect against passive attacks where an attacker tries to silently observe the data lines as the data lines move on and off the processor die. Some processors include an encryption module that encrypts sensitive data before the data is stored into a protected region of the memory. On a memory read to the protected region, the data line is decrypted before being fed into the processor.
The encryption and decryption algorithms can be chosen based on the security level required by the user. One possible choice of encryption is counter mode encryption. In counter mode encryption, the cryptographic task of encrypting/decrypting a data line is decoupled from the data itself. An example of counter mode encryption uses the AESk encryption algorithm to encrypt a seed, which is uniquely associated with each data line but independent of the data.
CryptoPad=AESk(Seed);
Encryption=Plaintext XOR CryptoPad;
Decryption=Ciphertext XOR CryptoPad.
To ensure the security of counter mode encryption, the seed needs to be unique both spatially and temporarily. Spatial uniqueness can be achieved by using the address of the data line as a component of the seed. Temporal uniqueness, on the other hand, can be achieved by associating a per-line counter with the data line subject to encryption. This counter is incremented each time the associated data line is written back to memory. This counter acts as the version of the data line.
Some processors implement a counter tree structure, which stores the version of each protected data line at the lowest level of the tree. The upper levels of the tree store a hierarchy of counters. The counter tree structure is stored in memory except the top level counters which are stored within the processor. This counter tree structure protects the memory region from replay attacks by a chain of verification operations. A write to a protected data line modifies a corresponding tree node at each level of the counter tree. When the protected data line is read, the processor verifies the value of the corresponding tree node at each level of the counter tree to authenticate the read result.
The existing replay protection algorithm suspends the processing of an incoming request if the request shares a tree node at any level of the counter tree structure with any of the requests in process. Thus, the processing of different memory requests is serialized, which increases memory access latency and degrades system performance.